home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / gnu / nethack.lha / nethack-3.1 / src / dog.c < prev    next >
C/C++ Source or Header  |  1993-01-25  |  13KB  |  501 lines

  1. /*    SCCS Id: @(#)dog.c    3.1    92/10/18    */
  2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  3. /* NetHack may be freely redistributed.  See license for details. */
  4.  
  5. #include "hack.h"
  6. #include "edog.h"
  7.  
  8. #define domestic(mtmp)    (mtmp->data->msound == MS_BARK || \
  9.              mtmp->data->msound == MS_MEW)
  10.  
  11. #ifdef OVLB
  12.  
  13. static int NDECL(pet_type);
  14.  
  15. void
  16. initedog(mtmp)
  17. register struct monst *mtmp;
  18. {
  19.     mtmp->mtame = domestic(mtmp) ? 10 : 5;
  20.     mtmp->mpeaceful = 1;
  21.     set_malign(mtmp); /* recalc alignment now that it's tamed */
  22.     mtmp->mleashed = 0;
  23.     mtmp->meating = 0;
  24.     EDOG(mtmp)->droptime = 0;
  25.     EDOG(mtmp)->dropdist = 10000;
  26.     EDOG(mtmp)->apport = 10;
  27.     EDOG(mtmp)->whistletime = 0;
  28.     EDOG(mtmp)->hungrytime = 1000 + moves;
  29. }
  30.  
  31. static int
  32. pet_type()
  33. {
  34.     register int pettype;
  35.  
  36.     switch (pl_character[0]) {
  37.         /* some character classes have restricted ideas of pets */
  38.         case 'C':
  39.         case 'S':
  40.             pettype = PM_LITTLE_DOG;
  41.             break;
  42.         case 'W':
  43.             pettype = PM_KITTEN;
  44.             break;
  45.         /* otherwise, see if the player has a preference */
  46.         default:
  47.             if (preferred_pet == 'c')
  48.                 pettype = PM_KITTEN;
  49.             else if (preferred_pet == 'd')
  50.                 pettype = PM_LITTLE_DOG;
  51.             else    pettype = rn2(2) ? PM_KITTEN : PM_LITTLE_DOG;
  52.             break;
  53.     }
  54.     return pettype;
  55. }
  56.  
  57. void
  58. make_familiar(otmp,x,y)
  59. register struct obj *otmp;
  60. xchar x, y;
  61. {
  62.     register struct monst *mtmp;
  63.     register struct permonst *pm;
  64.  
  65. top:
  66.     if (otmp) pm = &mons[otmp->corpsenm]; /* Figurine; otherwise spell */
  67.     else if (rn2(3)) {
  68.         if (!(pm = rndmonst())) {
  69.         pline("There seems to be nothing available for a familiar.");
  70.         return;
  71.         }
  72.     }
  73.     else pm = &mons[pet_type()];
  74.  
  75.     pm->pxlth += sizeof(struct edog);
  76.     mtmp = makemon(pm, x, y);
  77.     pm->pxlth -= sizeof(struct edog);
  78.     if (!mtmp) { /* monster was genocided */
  79.         if (otmp)
  80.         pline("The figurine writhes and then shatters into pieces!");
  81.         else goto top;
  82.         /* rndmonst() returns something not genocided always, so this
  83.          * means it was a cat or dog; loop back to try again until
  84.          * either rndmonst() is called, or if only one of cat/dog
  85.          * was genocided, they get the other.
  86.          */
  87.         return;
  88.     }
  89.     initedog(mtmp);
  90.     mtmp->msleep = 0;
  91.     if (otmp && otmp->cursed) { /* cursed figurine */
  92.         You("get a bad feeling about this.");
  93.         mtmp->mtame = mtmp->mpeaceful = 0;
  94.         newsym(mtmp->mx, mtmp->my);
  95.     }
  96.     set_malign(mtmp); /* more alignment changes */
  97. }
  98.  
  99. struct monst *
  100. makedog()
  101. {
  102.     register struct monst *mtmp;
  103.     char *petname;
  104.     int   pettype;
  105.     static int petname_used = 0;
  106.  
  107.     pettype = pet_type();
  108.     if (pettype == PM_LITTLE_DOG)
  109.         petname = dogname;
  110.     else
  111.         petname = catname;
  112.  
  113.     mons[pettype].pxlth = sizeof(struct edog);
  114.     mtmp = makemon(&mons[pettype], u.ux, u.uy);
  115.     mons[pettype].pxlth = 0;
  116.  
  117.     if(!mtmp) return((struct monst *) 0); /* pets were genocided */
  118.  
  119.     if (!petname_used++ && *petname)
  120.         mtmp = christen_monst(mtmp, petname);
  121.  
  122.     initedog(mtmp);
  123.     return(mtmp);
  124. }
  125.  
  126. void
  127. losedogs()
  128. {
  129.     register struct monst *mtmp,*mtmp0,*mtmp2;
  130.     int num_segs;
  131.  
  132.     while(mtmp = mydogs){
  133.         mydogs = mtmp->nmon;
  134.         mtmp->nmon = fmon;
  135.         fmon = mtmp;
  136.         if (mtmp->isshk)
  137.             set_residency(mtmp, FALSE);
  138.  
  139.         num_segs = mtmp->wormno;
  140.         /* baby long worms have no tail so don't use is_longworm() */
  141.         if ( (mtmp->data == &mons[PM_LONG_WORM]) &&
  142.              (mtmp->wormno = get_wormno()) ) {
  143.             initworm(mtmp, num_segs);
  144.             /* tail segs are not yet initialized or displayed */
  145.         } else mtmp->wormno = 0;
  146.         mnexto(mtmp);
  147.     }
  148.  
  149. #if defined(LINT) || defined(GCC_WARN)
  150.     mtmp0 = (struct monst *)0;
  151. #endif
  152.     for(mtmp = migrating_mons; mtmp; mtmp = mtmp2) {
  153.         mtmp2 = mtmp->nmon;
  154.         if(mtmp->mx == u.uz.dnum && mtmp->mux == u.uz.dlevel) {
  155.             mtmp->mx = 0;           /* save xyloc in mtmp->my */
  156.             mtmp->mux = u.ux; mtmp->muy = u.uy; /* not really req'd */
  157.             if(mtmp == migrating_mons)
  158.             migrating_mons = mtmp->nmon;
  159.             else
  160.             mtmp0->nmon = mtmp->nmon;
  161.             mtmp->nmon = fmon;
  162.             fmon = mtmp;
  163.             num_segs = mtmp->wormno;
  164.             if ( (mtmp->data == &mons[PM_LONG_WORM]) &&
  165.              (mtmp->wormno = get_wormno()) ) {
  166.             initworm(mtmp, num_segs);
  167.             /* tail segs are not yet initialized or displayed */
  168.             } else mtmp->wormno = 0;
  169.  
  170.             if(mtmp->mlstmv < monstermoves-1) {
  171.             /* heal monster for time spent in limbo */
  172.             long nmv = monstermoves - mtmp->mlstmv - 1;
  173.  
  174.             /* might stop being afraid, blind or frozen */
  175.             /* set to 1 and allow final decrement in movemon() */
  176.             if(nmv >= (long)mtmp->mblinded) mtmp->mblinded = 1;
  177.             else mtmp->mblinded -= nmv;
  178.             if(nmv >= (long)mtmp->mfrozen) mtmp->mfrozen = 1;
  179.             else mtmp->mfrozen -= nmv;
  180.             if(nmv >= (long)mtmp->mfleetim) mtmp->mfleetim = 1;
  181.             else mtmp->mfleetim -= nmv;
  182.  
  183.             /* might be able to use special ability again */
  184.             if(nmv > (long)mtmp->mspec_used) mtmp->mspec_used = 0;
  185.             else mtmp->mspec_used -= nmv;
  186.  
  187.             if(!regenerates(mtmp->data)) nmv /= 20;
  188.             if((long)mtmp->mhp + nmv >= (long)mtmp->mhpmax)
  189.                 mtmp->mhp = mtmp->mhpmax;
  190.             else mtmp->mhp += nmv;
  191.             mtmp->mlstmv = monstermoves-1;
  192.             }
  193.  
  194.             if (mtmp->data->geno & G_GENOD) {
  195. #ifdef KOPS
  196.             allow_kops = FALSE;
  197. #endif
  198.             mondead(mtmp);    /* must put in fmon list first */
  199. #ifdef KOPS
  200.             allow_kops = TRUE;
  201. #endif
  202.             } else if (mtmp->isshk && mtmp->mpeaceful)
  203.             home_shk(mtmp, TRUE);
  204.             else switch(mtmp->my) {
  205.             xchar *xlocale, *ylocale;
  206.  
  207.             case 1: xlocale = &xupstair; ylocale = &yupstair;
  208.                 goto common;
  209.             case 2: xlocale = &xdnstair; ylocale = &ydnstair;
  210.                 goto common;
  211.             case 3: xlocale = &xupladder; ylocale = &yupladder;
  212.                 goto common;
  213.             case 4: xlocale = &xdnladder; ylocale = &ydnladder;
  214.                 goto common;
  215.             case 5: xlocale = &sstairs.sx; ylocale = &sstairs.sy;
  216.                 goto common;
  217. common:
  218.                 if (*xlocale && *ylocale) {
  219.                 (void) mnearto(mtmp, *xlocale, *ylocale, FALSE);
  220.                     break;
  221.                 } /* else fall through */
  222.             default: 
  223.                 rloc(mtmp);
  224.                 break;
  225.             }
  226.         } else
  227.             mtmp0 = mtmp;
  228.         if (mtmp->isshk)
  229.             set_residency(mtmp, FALSE);
  230.     }
  231. }
  232.  
  233. #endif /* OVLB */
  234. #ifdef OVL2
  235.  
  236. void
  237. keepdogs()
  238. {
  239.     register struct monst *mtmp;
  240.     register struct obj *obj;
  241.     int num_segs = 0;
  242.  
  243.     for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
  244.         if(((monnear(mtmp, u.ux, u.uy) && levl_follower(mtmp)) ||
  245.         /* the wiz will level t-port from anywhere to chase
  246.            the amulet; if you don't have it, will chase you
  247.            only if in range. -3. */
  248.             (u.uhave.amulet && mtmp->iswiz))
  249.             && !mtmp->msleep && mtmp->mcanmove) {
  250.  
  251.         /* long worms can now change levels! - Norm */
  252.  
  253.         if (mtmp->mtame && mtmp->meating && canseemon(mtmp)) {
  254.             pline("%s is still eating.", Monnam(mtmp));
  255.             goto merge;
  256.         }
  257.         if (mon_has_amulet(mtmp)) {
  258.             pline("%s seems very disoriented for a moment.",
  259.                 Monnam(mtmp));
  260.         merge:
  261. #ifdef WALKIES
  262.             if (mtmp->mleashed) {
  263.                 pline("%s leash suddenly comes loose.",
  264.                     humanoid(mtmp->data)
  265.                         ? (mtmp->female ? "Her" : "His")
  266.                         : "Its");
  267.                 m_unleash(mtmp);
  268.             }
  269. #endif
  270.             continue;
  271.         }
  272.         if (mtmp->isshk)
  273.             set_residency(mtmp, TRUE);
  274.  
  275.         if (mtmp->wormno) {
  276.             /* NOTE: worm is truncated to # segs = max wormno size */
  277.             num_segs = min(count_wsegs(mtmp), MAX_NUM_WORMS - 1);
  278.             wormgone(mtmp);
  279.         }
  280.  
  281.         /* set minvent's obj->no_charge to 0 */
  282.         for(obj = mtmp->minvent; obj; obj = obj->nobj) {
  283.             if(Is_container(obj))
  284.                 picked_container(obj); /* does the right thing */
  285.             obj->no_charge = 0;
  286.         }
  287.  
  288.         relmon(mtmp);
  289.         newsym(mtmp->mx,mtmp->my);
  290.         mtmp->mx = mtmp->my = 0; /* avoid mnexto()/MON_AT() problem */
  291.         mtmp->wormno = num_segs;
  292.         mtmp->nmon = mydogs;
  293.         mydogs = mtmp;
  294.         keepdogs();    /* we destroyed the link, so use recursion */
  295.         return;        /* (admittedly somewhat primitive) */
  296.     }
  297. }
  298.  
  299. #endif /* OVL2 */
  300. #ifdef OVLB
  301.  
  302. void
  303. migrate_to_level(mtmp, tolev, xyloc) 
  304.     register struct monst *mtmp; 
  305.     xchar tolev;      /* destination level */
  306.     xchar xyloc;    /* destination xy location: */
  307.             /*     0: rnd,
  308.              *    1: <,
  309.              *    2: >,
  310.              *    3: < ladder,
  311.              *    4: > ladder,
  312.              *    5: sstairs
  313.              */ 
  314. {
  315.         register struct obj *obj;
  316.     int num_segs = 0;    /* count of worm segments */
  317.  
  318.     if (mtmp->isshk)
  319.         set_residency(mtmp, TRUE);
  320.  
  321.     if (mtmp->wormno) {
  322.       /* **** NOTE: worm is truncated to # segs = max wormno size **** */
  323.         num_segs = min(count_wsegs(mtmp), MAX_NUM_WORMS - 1);
  324.         wormgone(mtmp);
  325.     }
  326.  
  327.     /* set minvent's obj->no_charge to 0 */
  328.     for(obj = mtmp->minvent; obj; obj = obj->nobj) {
  329.         if(Is_container(obj))
  330.             picked_container(obj); /* does the right thing */
  331.         obj->no_charge = 0;
  332.     }
  333.  
  334.     relmon(mtmp);
  335.     mtmp->nmon = migrating_mons;
  336.     migrating_mons = mtmp;
  337. #ifdef WALKIES
  338.     if (mtmp->mleashed)  {
  339.         pline("The leash comes off!");
  340.         m_unleash(mtmp);
  341.     }
  342. #endif
  343.     mtmp->mtame = 0;
  344.     newsym(mtmp->mx,mtmp->my);
  345.     /* make sure to reset mtmp->[mx,my] to 0 when releasing, */
  346.     /* so rloc() on next level doesn't affect MON_AT() state */
  347.     mtmp->mx = ledger_to_dnum((xchar)tolev); 
  348.     mtmp->mux = ledger_to_dlev((xchar)tolev); 
  349.     mtmp->my = xyloc;
  350.     mtmp->muy = 0;
  351.     mtmp->wormno = num_segs;
  352.     mtmp->mlstmv = monstermoves;
  353. }
  354.  
  355. #endif /* OVLB */
  356. #ifdef OVL1
  357.  
  358. /* return quality of food; the lower the better */
  359. /* fungi will eat even tainted food */
  360. int
  361. dogfood(mon,obj)
  362. struct monst *mon;
  363. register struct obj *obj;
  364. {
  365.     boolean carni = carnivorous(mon->data);
  366.     boolean herbi = herbivorous(mon->data);
  367.     struct permonst *fptr = &mons[obj->corpsenm];
  368.  
  369.     switch(obj->oclass) {
  370.     case FOOD_CLASS:
  371.         if (obj->otyp == CORPSE &&
  372.         ((obj->corpsenm == PM_COCKATRICE && !resists_ston(mon->data))
  373.          || is_rider(fptr)))
  374.             return TABU;
  375.  
  376.         if (!carni && !herbi)
  377.             return (obj->cursed ? UNDEF : APPORT);
  378.  
  379.         switch (obj->otyp) {
  380.         case TRIPE_RATION:
  381.             return (carni ? DOGFOOD : MANFOOD);
  382.         case EGG:
  383.             if (obj->corpsenm == PM_COCKATRICE &&
  384.                         !resists_ston(mon->data))
  385.             return POISON;
  386.             return (carni ? CADAVER : MANFOOD);
  387.         case CORPSE:
  388.             if ((obj->age+50 <= monstermoves
  389.                         && obj->corpsenm != PM_LIZARD
  390.                         && mon->data->mlet != S_FUNGUS) ||
  391.             (acidic(&mons[obj->corpsenm]) &&
  392.                         !resists_acid(mon->data)) ||
  393.             (poisonous(&mons[obj->corpsenm]) &&
  394.                         !resists_poison(mon->data)))
  395.             return POISON;
  396.             else if (fptr->mlet == S_FUNGUS)
  397.             return (herbi ? CADAVER : MANFOOD);
  398.             else if (is_meaty(fptr))
  399.                 return (carni ? CADAVER : MANFOOD);
  400.             else return (carni ? ACCFOOD : MANFOOD);
  401.         case CLOVE_OF_GARLIC:
  402.             return (is_undead(mon->data) ? TABU :
  403.                 (herbi ? ACCFOOD : MANFOOD));
  404.         case TIN:
  405.             return (metallivorous(mon->data) ? ACCFOOD : MANFOOD);
  406.         case APPLE:
  407.         case CARROT:
  408.             return (herbi ? DOGFOOD : MANFOOD);
  409.         case BANANA:
  410.             return ((mon->data->mlet == S_YETI) ? DOGFOOD :
  411.                 (herbi ? ACCFOOD : MANFOOD));
  412.         default:
  413. #ifdef TUTTI_FRUTTI
  414.             return (obj->otyp > SLIME_MOLD ?
  415. #else
  416.             return (obj->otyp > CLOVE_OF_GARLIC ?
  417. #endif
  418.                 (carni ? ACCFOOD : MANFOOD) :
  419.                 (herbi ? ACCFOOD : MANFOOD));
  420.         }
  421.     default:
  422.         if (hates_silver(mon->data) && 
  423.         objects[obj->otyp].oc_material == SILVER)
  424.         return(TABU);
  425.         if (mon->data == &mons[PM_GELATINOUS_CUBE] && is_organic(obj))
  426.         return(ACCFOOD);
  427.         if (metallivorous(mon->data) && is_metallic(obj))
  428.         /* Ferrous based metals are preferred. */
  429.         return(objects[obj->otyp].oc_material == IRON ? DOGFOOD :
  430.                ACCFOOD);
  431.         if(!obj->cursed && obj->oclass != BALL_CLASS &&
  432.                         obj->oclass != CHAIN_CLASS)
  433.         return(APPORT);
  434.         /* fall into next case */
  435.     case ROCK_CLASS:
  436.         return(UNDEF);
  437.     }
  438. }
  439.  
  440. #endif /* OVL1 */
  441. #ifdef OVLB
  442.  
  443. struct monst *
  444. tamedog(mtmp, obj)
  445. register struct monst *mtmp;
  446. register struct obj *obj;
  447. {
  448.     register struct monst *mtmp2;
  449.  
  450.     /* The Wiz, Medusa and the quest nemeses aren't even made peaceful. */
  451.     if (mtmp->iswiz || mtmp->data == &mons[PM_MEDUSA]
  452. #ifdef MULDGN
  453.         || (mtmp->data->mflags3 & M3_WANTSARTI)
  454. #endif
  455.         )
  456.         return((struct monst *)0);
  457.  
  458.     /* worst case, at least he'll be peaceful. */
  459.     mtmp->mpeaceful = 1;
  460.     set_malign(mtmp);
  461.     if(flags.moonphase == FULL_MOON && night() && rn2(6) && obj
  462.                         && mtmp->data->mlet == S_DOG)
  463.         return((struct monst *)0);
  464.  
  465.     /* If we cannot tame him, at least he's no longer afraid. */
  466.     mtmp->mflee = 0;
  467.     mtmp->mfleetim = 0;
  468.     if(mtmp->mtame || !mtmp->mcanmove ||
  469.        /* monsters with conflicting structures cannot be tamed */
  470.        mtmp->isshk || mtmp->isgd || mtmp->ispriest || mtmp->isminion ||
  471. #ifdef POLYSELF
  472.        is_human(mtmp->data) || (is_demon(mtmp->data) && !is_demon(uasmon))
  473. #else
  474.        is_human(mtmp->data) || is_demon(mtmp->data)
  475. #endif
  476.        || (mtmp->data->mflags3 &
  477.            (M3_WANTSAMUL|M3_WANTSBELL|M3_WANTSBOOK|M3_WANTSCAND))
  478.        )
  479.         return((struct monst *)0);
  480.     if(obj) {
  481.         if(dogfood(mtmp, obj) >= MANFOOD) return((struct monst *)0);
  482.         if(cansee(mtmp->mx,mtmp->my))
  483.             pline("%s devours the %s.", Monnam(mtmp), xname(obj));
  484.         obfree(obj, (struct obj *)0);
  485.     }
  486.     if (u.uswallow && mtmp == u.ustuck)
  487.         expels(mtmp, mtmp->data, TRUE);
  488.     mtmp2 = newmonst(sizeof(struct edog) + mtmp->mnamelth);
  489.     *mtmp2 = *mtmp;
  490.     mtmp2->mxlth = sizeof(struct edog);
  491.     if(mtmp->mnamelth) Strcpy(NAME(mtmp2), NAME(mtmp));
  492.     initedog(mtmp2);
  493.     replmon(mtmp,mtmp2);
  494.     newsym(mtmp2->mx, mtmp2->my);
  495.     return(mtmp2);
  496. }
  497.  
  498. #endif /* OVLB */
  499.  
  500. /*dog.c*/
  501.